package com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.util;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xyht.sca_s.student_manage_system.modules.org.entity.OrgNode;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgStructure;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgUserRelation;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgStructureMapper;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgUserRelationMapper;
import com.xyht.sca_s.student_manage_system.modules.org.util.NodeUtil;
import com.xyht.sca_s.student_manage_system.modules.student.entity.SmsStudentInfo;
import com.xyht.sca_s.student_manage_system.modules.student.entity.SmsUserStudentRelation;
import com.xyht.sca_s.student_manage_system.modules.student.mapper.SmsStudentInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.student.mapper.SmsUserStudentRelationMapper;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.*;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.PlanAndStatusListResp;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.SmsWnsChargeOrgItemResp;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.SmsWnsChargePlanStudentStatusResp;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.StuOrgInfoResp;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.*;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.SmsWnsChargeOrgItemService;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.SmsWnsChargePlanStudentStatusService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.ChargePlanConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.RegistrationProcessDetailConstant.REGISTRATION_PROCESS_DETAIL_SORT_TWO;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.RegistrationProcessDetailConstant.REGISTRATION_PROCESS_DETAIL_STATUS_NOT_START;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.StudentLoanAmountRecordConstant.STUDENT_LOAN_AMOUNT_RECORD_DES_APPLY_PASS;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.StudentLoanAmountRecordConstant.STUDENT_LOAN_AMOUNT_RECORD_TYPE_LOAN_AMOUNT;

@Component
public class CategoryItemUtil {
    @Resource
    private SmsWnsChargePlanMapper smsWnsChargePlanMapper;
    @Resource
    private SmsWnsChargeCategoryMapper smsWnsChargeCategoryMapper;
    @Resource
    private SmsWnsChargeCategoryDetailMapper smsWnsChargeCategoryDetailMapper;
    @Resource
    @Lazy
    private SmsWnsChargeOrgItemService smsWnsChargeOrgItemService;
    @Resource
    private SmsUserMapper smsUserMapper;
    @Resource
    private SmsUserStudentRelationMapper smsUserStudentRelationMapper;
    @Resource
    private SmsStudentInfoMapper smsStudentInfoMapper;
    @Resource
    private SmsOrgStructureMapper smsOrgStructureMapper;
    @Resource
    private SmsOrgUserRelationMapper smsOrgUserRelationMapper;
    @Resource
    private SmsWnsChargePlanStudentStatusService smsWnsChargePlanStudentStatusService;
    @Resource
    private SmsWnsRegistrationProcessDetailMapper smsWnsRegistrationProcessDetailMapper;
    @Resource
    private SmsWnsStudentLoanAmountMapper smsWnsStudentLoanAmountMapper;
    @Resource
    private SmsWnsStudentLoanApplyMapper smsWnsStudentLoanApplyMapper;
    @Resource
    private SmsWnsChargeOrgItemMapper smsWnsChargeOrgItemMapper;
    @Resource
    private SmsWnsStudentLoanAmountRecordMapper smsWnsStudentLoanAmountRecordMapper;

    /**
     * 通过计划id初始化收费项
     *
     * @param planId 计划id
     * @return 是否初始化成功
     */
    @Transactional
    public boolean initializeCategoryItemByPlanId(String planId) {
        SmsWnsChargePlan plan = smsWnsChargePlanMapper.selectById(planId);
        if (plan == null || isNullOrEmpty(plan.getDetailIdList(), plan.getIdList())) {
            return false;
        }

        // 获取分类详情集合
        List<String> detailIdList = JSON.parseArray(plan.getDetailIdList(), String.class);
        List<SmsWnsChargeCategoryDetail> detailList = smsWnsChargeCategoryDetailMapper.selectBatchIds(detailIdList);
        if (detailList.isEmpty()) {
            return false;
        }

        // 获取 组织id/stuId 集合
        List<String> idList = JSON.parseArray(plan.getIdList(), String.class);
        if (idList.isEmpty()) {
            return false;
        }

        // 移除所有收费项
        smsWnsChargeOrgItemService.remove(new LambdaQueryWrapper<SmsWnsChargeOrgItem>()
                .eq(SmsWnsChargeOrgItem::getPlanId, planId));
        // 移除所有学生应缴费项
        smsWnsChargePlanStudentStatusService.remove(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                .eq(SmsWnsChargePlanStudentStatus::getPlanId, planId));

        // 获取全部组织
        List<SmsOrgStructure> orgList = smsOrgStructureMapper.selectList(new QueryWrapper<>());
        List<OrgNode> orgNodeList = orgList.stream().map(orgStructure -> {
            OrgNode orgNode = new OrgNode();
            BeanUtils.copyProperties(orgStructure, orgNode);
            return orgNode;
        }).collect(Collectors.toList());

        // 初始化收费项
        List<SmsWnsChargePlanStudentStatus> studentStatusList = new ArrayList<>();
        for (SmsWnsChargeCategoryDetail categoryDetail : detailList) {
            for (String id : idList) {
                SmsWnsChargeOrgItem chargeOrgItem = new SmsWnsChargeOrgItem();
                chargeOrgItem.setPlanId(planId);
                chargeOrgItem.setCategoryId(categoryDetail.getCategoryId());
                chargeOrgItem.setCategoryDetailId(categoryDetail.getId());
                chargeOrgItem.setOrgId(id);
                // 设置收费金额
                if (categoryDetail.getHasDefaultPrice()) {
                    chargeOrgItem.setAmount(categoryDetail.getDefaultPrice());
                } else {
                    chargeOrgItem.setAmount(BigDecimal.valueOf(0));
                }
                chargeOrgItem.setDiscountAmount(BigDecimal.valueOf(0));
                smsWnsChargeOrgItemService.save(chargeOrgItem);

                // 设置每个学生应收费
                if (plan.getRangeType() == CHARGE_PLAN_RANGE_TYPE_MAJOR) {
                    // 获取年级
                    List<SmsOrgStructure> gradeOrgList = smsOrgStructureMapper.selectList(new LambdaQueryWrapper<SmsOrgStructure>()
                            .eq(SmsOrgStructure::getParentId, id)
                            .eq(SmsOrgStructure::getOrgName, plan.getGrade()));

                    // 获取当前年级下所有userId
                    List<Integer> childIdList = NodeUtil.getChildNodes(orgNodeList, gradeOrgList.get(0).getId());
                    List<SmsOrgUserRelation> userRelationList = smsOrgUserRelationMapper.selectList(new LambdaQueryWrapper<SmsOrgUserRelation>()
                            .in(SmsOrgUserRelation::getOrgId, childIdList));

                    List<String> gradeOrgUserIdList = userRelationList.stream().map(SmsOrgUserRelation::getUserId).distinct().collect(Collectors.toList());
                    // 新生缴费计划只包含新生
                    if (plan.getType() == CHARGE_PLAN_TYPE_NEW_STUDENT) {
                        List<SmsUser> userList = smsUserMapper.selectList(new LambdaQueryWrapper<SmsUser>()
                                .eq(SmsUser::getIsUse, 0) // 新生
                                .in(SmsUser::getId, gradeOrgUserIdList));
                        gradeOrgUserIdList = userList.stream().map(SmsUser::getId).collect(Collectors.toList());

                        List<SmsWnsRegistrationProcessDetail> processDetailList = smsWnsRegistrationProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsWnsRegistrationProcessDetail>()
                                .in(SmsWnsRegistrationProcessDetail::getUserId, gradeOrgUserIdList)
                                .eq(SmsWnsRegistrationProcessDetail::getSort, REGISTRATION_PROCESS_DETAIL_SORT_TWO)
                                .ne(SmsWnsRegistrationProcessDetail::getStatus, REGISTRATION_PROCESS_DETAIL_STATUS_NOT_START));// 财务处报道
                        if (!processDetailList.isEmpty()) {
                            SmsWnsRegistrationProcessDetail detail = new SmsWnsRegistrationProcessDetail();
                            detail.setStatus(REGISTRATION_PROCESS_DETAIL_STATUS_NOT_START);
                            List<String> updDetailIdList = processDetailList.stream().map(SmsWnsRegistrationProcessDetail::getId).collect(Collectors.toList());
                            smsWnsRegistrationProcessDetailMapper.update(detail, new LambdaQueryWrapper<SmsWnsRegistrationProcessDetail>()
                                    .in(SmsWnsRegistrationProcessDetail::getId, updDetailIdList));
                        }
                    }
                    // 设置学生个人缴费情况
                    for (String gradeOrgUserId : gradeOrgUserIdList) {
                        String stuId = getStuIdByUserId(gradeOrgUserId);
                        if (isNullOrEmpty(stuId)) {
                            continue;
                        }
                        SmsWnsChargePlanStudentStatus studentStatus = initStudentStatus(chargeOrgItem, gradeOrgUserId, stuId);
                        studentStatusList.add(studentStatus);
                    }
                } else if (plan.getRangeType() == CHARGE_PLAN_RANGE_TYPE_CLASS) {
                    SmsOrgStructure classOrg = smsOrgStructureMapper.selectById(id);

                    // 获取当前班级下所有userId
                    List<Integer> childIdList = NodeUtil.getChildNodes(orgNodeList, classOrg.getId());
                    List<SmsOrgUserRelation> userRelationList = smsOrgUserRelationMapper.selectList(new LambdaQueryWrapper<SmsOrgUserRelation>()
                            .in(SmsOrgUserRelation::getOrgId, childIdList));

                    List<String> classOrgUserIdList = userRelationList.stream().map(SmsOrgUserRelation::getUserId).distinct().collect(Collectors.toList());
                    for (String classOrgUserId : classOrgUserIdList) {
                        String stuId = getStuIdByUserId(classOrgUserId);
                        if (isNullOrEmpty(stuId)) {
                            continue;
                        }
                        SmsWnsChargePlanStudentStatus studentStatus = initStudentStatus(chargeOrgItem, classOrgUserId, stuId);
                        studentStatusList.add(studentStatus);
                    }
                } else if (plan.getRangeType() == CHARGE_PLAN_RANGE_TYPE_USER) {
                    List<SmsUserStudentRelation> userStudentRelationList = smsUserStudentRelationMapper.selectList(new LambdaQueryWrapper<SmsUserStudentRelation>()
                            .eq(SmsUserStudentRelation::getStuId, id));

                    SmsWnsChargePlanStudentStatus studentStatus = initStudentStatus(chargeOrgItem, userStudentRelationList.get(0).getUserId(), id);
                    studentStatusList.add(studentStatus);
                }
            }
        }

        // 保存学生应收费
        smsWnsChargePlanStudentStatusService.saveBatch(studentStatusList);

        // 修改计划为已初始化
        plan.setIsInitialized(true);
        smsWnsChargePlanMapper.updateById(plan);

        return true;
    }

    /**
     * 根据userId获取属于自己的最新计划(新生)
     *
     * @param userId userId
     * @return 属于自己最新计划(新生)/null
     */
    public SmsWnsChargePlan getNewStuPlanByUserId(String userId) {
        // 获取学生信息
        StuOrgInfoResp stuOrgInfoResp = getStuOrgInfoByUserId(userId);
        if (stuOrgInfoResp == null) {
            return null;
        }

        // (新生)获取包含自己的最新计划
        List<SmsWnsChargePlan> planList = smsWnsChargePlanMapper.selectList(new LambdaQueryWrapper<SmsWnsChargePlan>()
                .eq(SmsWnsChargePlan::getType, CHARGE_PLAN_TYPE_NEW_STUDENT)
                .eq(SmsWnsChargePlan::getGrade, stuOrgInfoResp.getGradeName())
                .eq(SmsWnsChargePlan::getIsPublish, true)
                .orderByDesc(SmsWnsChargePlan::getCreateTime));
        if (planList.isEmpty()) {
            return null;
        }
        SmsWnsChargePlan plan = null;
        for (SmsWnsChargePlan aPlan : planList) {
            List<String> idList = JSON.parseArray(aPlan.getIdList(), String.class);
            if (idList.contains(stuOrgInfoResp.getMajorId())) { // 包含当前学生
                plan = aPlan;
                break;
            }
        }

        return plan;
    }

    /**
     * 添加新生收费项状态
     *
     * @param userId userId
     * @return true/false
     */
    @Transactional
    public boolean addCategoryItem(String userId) {
        // 获取学生信息
        StuOrgInfoResp stuOrgInfoResp = getStuOrgInfoByUserId(userId);
        if (stuOrgInfoResp == null) {
            return false;
        }

        // (新生)获取包含自己的最新计划
        List<SmsWnsChargePlan> planList = smsWnsChargePlanMapper.selectList(new LambdaQueryWrapper<SmsWnsChargePlan>()
                .eq(SmsWnsChargePlan::getType, CHARGE_PLAN_TYPE_NEW_STUDENT)
                .eq(SmsWnsChargePlan::getGrade, stuOrgInfoResp.getGradeName())
                .eq(SmsWnsChargePlan::getIsPublish, true)
                .orderByDesc(SmsWnsChargePlan::getCreateTime));
        if (planList.isEmpty()) {
            return false;
        }
        SmsWnsChargePlan plan = null;
        for (SmsWnsChargePlan aPlan : planList) {
            List<String> idList = JSON.parseArray(aPlan.getIdList(), String.class);
            if (idList.contains(stuOrgInfoResp.getMajorId())) {
                plan = aPlan;

                // 校验该生是否生成收费计划
                int count = smsWnsChargePlanStudentStatusService.count(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                        .eq(SmsWnsChargePlanStudentStatus::getUserId, userId)
                        .eq(SmsWnsChargePlanStudentStatus::getPlanId, plan.getId()));
                if (count > 0) {
                    return true;
                }

                break;
            }
        }
        // 没有获取到属于自己的计划
        if (plan == null) {
            return false;
        }

        // 获取分类详情集合
        List<String> detailIdList = JSON.parseArray(plan.getDetailIdList(), String.class);
        List<SmsWnsChargeCategoryDetail> detailList = smsWnsChargeCategoryDetailMapper.selectBatchIds(detailIdList);
        if (detailList.isEmpty()) {
            return false;
        }

        // 添加收费项缴费情况
        List<SmsWnsChargePlanStudentStatus> studentStatusList = new ArrayList<>();
        for (String detailId : detailIdList) {
            SmsWnsChargeOrgItem orgItem = smsWnsChargeOrgItemService.getOne(new LambdaQueryWrapper<SmsWnsChargeOrgItem>()
                    .eq(SmsWnsChargeOrgItem::getPlanId, plan.getId())
                    .eq(SmsWnsChargeOrgItem::getOrgId, stuOrgInfoResp.getMajorId())
                    .eq(SmsWnsChargeOrgItem::getCategoryDetailId, detailId));

            String stuId = getStuIdByUserId(userId);
            if (isNullOrEmpty(stuId)) {
                return false;
            }
            SmsWnsChargePlanStudentStatus studentStatus = initStudentStatus(orgItem, userId, stuId);
            studentStatusList.add(studentStatus);
        }

        // 保存学生应收费
        smsWnsChargePlanStudentStatusService.saveBatch(studentStatusList);

        return true;
    }

    /**
     * 向某计划添加某用户
     *
     * @param planId 计划id
     * @param orgId  sms_wns_charge_org_item中orgId
     * @param userId 用户id
     * @return true/false
     */
    @Transactional
    public boolean addCategoryItem(String planId, String orgId, String userId) {
        if (isNullOrEmpty(planId, userId)) {
            return false;
        }

        SmsWnsChargePlan plan = smsWnsChargePlanMapper.selectById(planId);
        if (plan == null) {
            return false;
        }

        // 获取分类详情集合
        List<String> detailIdList = JSON.parseArray(plan.getDetailIdList(), String.class);
        List<SmsWnsChargeCategoryDetail> detailList = smsWnsChargeCategoryDetailMapper.selectBatchIds(detailIdList);
        if (detailList.isEmpty()) {
            return false;
        }

        String stuId = getStuIdByUserId(userId);
        if (isNullOrEmpty(stuId)) {
            return false;
        }

        // 添加收费项缴费情况
        List<SmsWnsChargePlanStudentStatus> studentStatusList = new ArrayList<>();
        List<SmsWnsChargeOrgItem> orgItemList = new ArrayList<>();
        for (String detailId : detailIdList) {
            SmsWnsChargeOrgItem orgItem = smsWnsChargeOrgItemService.getOne(new LambdaQueryWrapper<SmsWnsChargeOrgItem>()
                    .eq(SmsWnsChargeOrgItem::getPlanId, plan.getId())
                    .eq(SmsWnsChargeOrgItem::getOrgId, orgId)
                    .eq(SmsWnsChargeOrgItem::getCategoryDetailId, detailId));
            if (orgItem == null) {
                return false;
            }

            if (plan.getRangeType() == CHARGE_PLAN_RANGE_TYPE_USER) {
                SmsWnsChargeOrgItem newOrgItem = new SmsWnsChargeOrgItem();
                BeanUtils.copyProperties(orgItem, newOrgItem, "id");
                newOrgItem.setOrgId(stuId);
                orgItemList.add(newOrgItem);
            }

            SmsWnsChargePlanStudentStatus studentStatus = initStudentStatus(orgItem, userId, stuId);
            studentStatusList.add(studentStatus);
        }

        // 保存收费项
        if (!orgItemList.isEmpty()) {
            List<String> idList = JSON.parseArray(plan.getIdList(), String.class);
            idList.add(stuId);
            plan.setIdList(JSON.toJSONString(idList.stream().distinct().collect(Collectors.toList())));
            smsWnsChargePlanMapper.updateById(plan);
            smsWnsChargeOrgItemService.saveBatch(orgItemList);
        }

        // 保存学生应收费
        smsWnsChargePlanStudentStatusService.saveBatch(studentStatusList);

        return true;
    }

    /**
     * 通过userId获取stuId
     *
     * @param userId userId
     * @return stuId/null
     */
    public String getStuIdByUserId(String userId) {
        List<SmsUserStudentRelation> userStudentRelationList = smsUserStudentRelationMapper.selectList(new LambdaQueryWrapper<SmsUserStudentRelation>()
                .eq(SmsUserStudentRelation::getUserId, userId));
        if (userStudentRelationList.isEmpty()) {
            return null;
        }

        return userStudentRelationList.get(0).getStuId();
    }

    /**
     * 初始化学生某项缴费状态
     *
     * @param item   收费项
     * @param userId userId
     * @param stuId  stuId
     * @return SmsWnsChargePlanStudentStatus
     */
    public SmsWnsChargePlanStudentStatus initStudentStatus(SmsWnsChargeOrgItem item, String userId, String stuId) {
        SmsWnsChargePlanStudentStatus studentStatus = new SmsWnsChargePlanStudentStatus();
        studentStatus.setPlanId(item.getPlanId());
        studentStatus.setCategoryId(item.getCategoryId());
        studentStatus.setCategoryDetailId(item.getCategoryDetailId());
        studentStatus.setChargeItemId(item.getId());
        studentStatus.setIsNecessary(false); // 默认不必交

        studentStatus.setTotalAmount(item.getAmount()); // 应缴金额
        studentStatus.setNeedPaymentAmount(item.getAmount()); // 欠费金额

        studentStatus.setPaymentAmount(BigDecimal.ZERO); // 实缴金额
        studentStatus.setGrantAmount(BigDecimal.ZERO); // 助学金分配金额
        studentStatus.setOfflineAmount(BigDecimal.ZERO); // 线下缴费金额
        studentStatus.setIsPaid(false);

        studentStatus.setUserId(userId);
        studentStatus.setStuId(stuId);
        return studentStatus;
    }

    /**
     * 根据计划id获取收费项
     *
     * @param planId 计划id
     * @param id     元素id
     * @return 收费项集合
     */
    public List<SmsWnsChargeOrgItemResp> getCategoryItemRespList(@NotNull String planId, @NotNull String id) {
        List<SmsWnsChargeOrgItemResp> categoryItemRespList;

        List<SmsWnsChargeOrgItem> categoryItemList = smsWnsChargeOrgItemService.list(new LambdaQueryWrapper<SmsWnsChargeOrgItem>()
                .eq(SmsWnsChargeOrgItem::getPlanId, planId)
                .eq(SmsWnsChargeOrgItem::getOrgId, id));
        categoryItemRespList = categoryItemList.stream().map(categoryItem -> {
            SmsWnsChargeOrgItemResp chargeItemResp = new SmsWnsChargeOrgItemResp();
            BeanUtils.copyProperties(categoryItem, chargeItemResp);

            return chargeItemResp;
        }).collect(Collectors.toList());

        return categoryItemRespList;
    }

    /**
     * 根据用户id获取学生组织信息
     *
     * @param userId 用户id
     * @return 学生组织信息, 失败返回null
     */
    public StuOrgInfoResp getStuOrgInfoByUserId(@NotNull String userId) {
        SmsUser user = smsUserMapper.selectById(userId);
        if (user == null) {
            return null;
        }

        List<SmsUserStudentRelation> userStudentRelationList = smsUserStudentRelationMapper.selectList(new LambdaQueryWrapper<SmsUserStudentRelation>()
                .eq(SmsUserStudentRelation::getUserId, userId));
        if (userStudentRelationList.isEmpty()) {
            return null;
        }

        SmsStudentInfo studentInfo = smsStudentInfoMapper.selectById(userStudentRelationList.get(0).getStuId());
        if (studentInfo == null) {
            return null;
        }

        List<SmsOrgUserRelation> userRelationList = smsOrgUserRelationMapper.selectList(new LambdaQueryWrapper<SmsOrgUserRelation>()
                .eq(SmsOrgUserRelation::getUserId, userId));
        if (userRelationList.isEmpty()) {
            return null;
        }

        SmsOrgStructure classOrg = smsOrgStructureMapper.selectById(userRelationList.get(0).getOrgId());
        if (classOrg == null || !classOrg.getLevel().equals("6")) {
            return null;
        }

        SmsOrgStructure gradeOrg = smsOrgStructureMapper.selectById(classOrg.getParentId());
        if (gradeOrg == null) {
            return null;
        }

        SmsOrgStructure majorOrg = smsOrgStructureMapper.selectById(gradeOrg.getParentId());
        if (majorOrg == null) {
            return null;
        }

        StuOrgInfoResp stuOrgInfoResp = new StuOrgInfoResp();
        stuOrgInfoResp.setStuId(studentInfo.getId());
        stuOrgInfoResp.setClassId(String.valueOf(classOrg.getId()));
        stuOrgInfoResp.setClassName(classOrg.getOrgName());
        stuOrgInfoResp.setGradeId(String.valueOf(gradeOrg.getId()));
        stuOrgInfoResp.setGradeName(gradeOrg.getOrgName());
        stuOrgInfoResp.setMajorId(String.valueOf(majorOrg.getId()));
        stuOrgInfoResp.setMajorName(majorOrg.getOrgName());

        return stuOrgInfoResp;
    }

    /**
     * 校验当前用户是否属于该计划
     *
     * @param planId 计划id
     * @param userId 用户id
     * @return true/false
     */
    public boolean planContainsUser(@NotNull String planId, @NotNull String userId) {
        StuOrgInfoResp stuOrgInfo = getStuOrgInfoByUserId(userId);
        if (stuOrgInfo == null) {
            return false;
        }

        SmsWnsChargePlan plan = smsWnsChargePlanMapper.selectById(planId);
        if (plan == null) {
            return false;
        }

        List<String> idList = JSON.parseArray(plan.getIdList(), String.class);
        boolean flag = false;

        if (plan.getRangeType() == CHARGE_PLAN_RANGE_TYPE_MAJOR) {
            if (stuOrgInfo.getGradeName().equals(plan.getGrade()) && idList.contains(stuOrgInfo.getMajorId())) {
                flag = true;
            }
        } else if (plan.getRangeType() == CHARGE_PLAN_RANGE_TYPE_CLASS) {
            if (idList.contains(stuOrgInfo.getClassId())) {
                flag = true;
            }
        } else if (plan.getRangeType() == CHARGE_PLAN_RANGE_TYPE_USER) {
            if (idList.contains(stuOrgInfo.getStuId())) {
                flag = true;
            }
        }

        return flag;
    }

    /**
     * 初始化类别数据
     */
    @Transactional
    public void initCategoryData() {
        smsWnsChargeCategoryDetailMapper.delete(new QueryWrapper<>());

        // 学费
        SmsWnsChargeCategory studyCategory = new SmsWnsChargeCategory("学费", 0, 0);
        smsWnsChargeCategoryMapper.insert(studyCategory);
        SmsWnsChargeCategoryDetail studyDetail = new SmsWnsChargeCategoryDetail(studyCategory.getId(), studyCategory.getSort(), studyCategory.getName(), 0);
        smsWnsChargeCategoryDetailMapper.insert(studyDetail);

        // 住宿费
        SmsWnsChargeCategory liveCategory = new SmsWnsChargeCategory("住宿费", 0, 1);
        smsWnsChargeCategoryMapper.insert(liveCategory);
    }

    /**
     * (新生)通过detailName获取收费项缴费状态
     *
     * @param userId     userId
     * @param detailName detailName
     * @return 收费项缴费状态, 获取失败返回null
     */
    public SmsWnsChargePlanStudentStatus getStatusByCategoryDetailName(String userId, String detailName) {
        SmsWnsChargeCategoryDetail detail = smsWnsChargeCategoryDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsChargeCategoryDetail>()
                .eq(SmsWnsChargeCategoryDetail::getName, detailName));
        if (detail == null) {
            return null;
        }

        SmsWnsChargePlan plan = getNewStuPlanByUserId(userId);
        if (plan == null) {
            return null;
        }

        SmsWnsChargePlanStudentStatus status = smsWnsChargePlanStudentStatusService.getOne(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                .eq(SmsWnsChargePlanStudentStatus::getPlanId, plan.getId())
                .eq(SmsWnsChargePlanStudentStatus::getUserId, userId)
                .eq(SmsWnsChargePlanStudentStatus::getCategoryDetailId, detail.getId()));

        return status;
    }

    /**
     * 通过stuId获取报到流程状态集合
     *
     * @param stuId stuId
     * @return 报到流程状态集合
     */
    public List<SmsWnsRegistrationProcessDetail> getProcessListByStuId(String stuId) {
        List<SmsWnsRegistrationProcessDetail> processDetailList = new ArrayList<>();

        List<SmsUserStudentRelation> userStudentRelationList = smsUserStudentRelationMapper.selectList(new LambdaQueryWrapper<SmsUserStudentRelation>()
                .eq(SmsUserStudentRelation::getStuId, stuId));
        if (userStudentRelationList.isEmpty()) {
            return processDetailList;
        }

        processDetailList = smsWnsRegistrationProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsWnsRegistrationProcessDetail>()
                .eq(SmsWnsRegistrationProcessDetail::getUserId, userStudentRelationList.get(0).getUserId())
                .orderByAsc(SmsWnsRegistrationProcessDetail::getSort));
        return processDetailList;
    }

    /**
     * 根据orgId获取某组织下的所有userId
     *
     * @param orgId orgId
     * @return userId集合
     */
    public List<String> getUserIdListByOrgId(Integer orgId) {
        List<String> userIdList = new ArrayList<>();
        if (orgId == null) {
            return userIdList;
        }

        // 获取全部组织
        List<SmsOrgStructure> orgList = smsOrgStructureMapper.selectList(new QueryWrapper<>());
        List<OrgNode> orgNodeList = orgList.stream().map(orgStructure -> {
            OrgNode orgNode = new OrgNode();
            BeanUtils.copyProperties(orgStructure, orgNode);
            return orgNode;
        }).collect(Collectors.toList());
        // 获取当前年级下所有userId
        List<Integer> childIdList = NodeUtil.getChildNodes(orgNodeList, orgId);
        List<SmsOrgUserRelation> userRelationList = smsOrgUserRelationMapper.selectList(new LambdaQueryWrapper<SmsOrgUserRelation>()
                .in(SmsOrgUserRelation::getOrgId, childIdList));
        if (userRelationList.isEmpty()) {
            return userIdList;
        }

        // 收集去重
        userIdList = userRelationList.stream().map(SmsOrgUserRelation::getUserId).distinct().collect(Collectors.toList());

        return userIdList;
    }

    /**
     * 根据orgId获取所有stuId
     *
     * @param orgId orgId
     * @return stuId集合
     */
    public List<String> getStuIdByOrgId(Integer orgId) {
        List<String> stuIdList = new ArrayList<>();

        List<String> userIdList = getUserIdListByOrgId(orgId);
        if (userIdList.isEmpty()) {
            return stuIdList;
        }

        return getStuIdListByUserIdList(userIdList);
    }

    /**
     * 根据userId集合获取stuId集合
     *
     * @param userIdList userId集合
     * @return stuId集合
     */
    public List<String> getStuIdListByUserIdList(List<String> userIdList) {
        List<String> stuIdList = new ArrayList<>();
        if (userIdList.isEmpty()) {
            return stuIdList;
        }

        List<SmsUserStudentRelation> userStudentRelationList = smsUserStudentRelationMapper.selectList(new LambdaQueryWrapper<SmsUserStudentRelation>()
                .in(SmsUserStudentRelation::getUserId, userIdList));
        if (userStudentRelationList.isEmpty()) {
            return stuIdList;
        }

        stuIdList = userStudentRelationList.stream().map(SmsUserStudentRelation::getStuId).distinct().collect(Collectors.toList());

        return stuIdList;
    }

    /**
     * 根据stuId获取收费总状态
     *
     * @param stuId stuId
     * @return 收费总状态
     */
    public SmsWnsChargePlanStudentStatusResp getTotalStatusByStuId(String stuId) {
        List<SmsWnsChargePlanStudentStatus> statusList = smsWnsChargePlanStudentStatusService.list(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                .eq(SmsWnsChargePlanStudentStatus::getStuId, stuId)
                .eq(SmsWnsChargePlanStudentStatus::getIsNecessary, true));

        // 计算总收费状态
        BigDecimal totalAmount = BigDecimal.valueOf(0);
        BigDecimal needPaymentAmount = BigDecimal.valueOf(0);
        BigDecimal paymentAmount = BigDecimal.valueOf(0);
        for (SmsWnsChargePlanStudentStatus status : statusList) {
            totalAmount = totalAmount.add(status.getTotalAmount() == null ? BigDecimal.valueOf(0) : status.getTotalAmount());
            needPaymentAmount = needPaymentAmount.add(status.getNeedPaymentAmount() == null ? BigDecimal.valueOf(0) : status.getNeedPaymentAmount());
            paymentAmount = paymentAmount.add(status.getPaymentAmount() == null ? BigDecimal.valueOf(0) : status.getPaymentAmount());
        }

        SmsWnsChargePlanStudentStatusResp statusResp = new SmsWnsChargePlanStudentStatusResp();
        statusResp.setTotalAmount(totalAmount);
        statusResp.setNeedPaymentAmount(needPaymentAmount);
        statusResp.setPaymentAmount(paymentAmount);

        return statusResp;
    }

    /**
     * 根据userId获取总欠费金额
     *
     * @param userId userId
     * @return 总欠费金额
     */
    public BigDecimal getTotalNeedPaymentAmountByUserId(String userId) {
        List<SmsWnsChargePlanStudentStatus> statusList = smsWnsChargePlanStudentStatusService.list(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                .eq(SmsWnsChargePlanStudentStatus::getUserId, userId)
                .eq(SmsWnsChargePlanStudentStatus::getIsNecessary, true)
                .eq(SmsWnsChargePlanStudentStatus::getIsPaid, false));

        // 计算总收费状态
        BigDecimal needPaymentAmount = BigDecimal.valueOf(0);
        for (SmsWnsChargePlanStudentStatus status : statusList) {
            needPaymentAmount = needPaymentAmount.add(status.getNeedPaymentAmount() == null ? BigDecimal.valueOf(0) : status.getNeedPaymentAmount());
        }

        return needPaymentAmount;
    }

    /**
     * 根据stuId获取收费计划以及收费情况状态集合
     *
     * @param stuId stuId
     * @return 收费计划以及收费情况状态集合
     */
    public List<PlanAndStatusListResp> getPlanAndStatusList(String stuId) {
        List<PlanAndStatusListResp> planAndStatusListRespList = new ArrayList<>();

        List<SmsWnsChargePlanStudentStatus> studentStatusList = smsWnsChargePlanStudentStatusService.list(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                .eq(SmsWnsChargePlanStudentStatus::getStuId, stuId));
        if (studentStatusList.isEmpty()) {
            return planAndStatusListRespList;
        }

        List<String> planIdList = studentStatusList.stream().map(SmsWnsChargePlanStudentStatus::getPlanId).distinct().collect(Collectors.toList());
        List<SmsWnsChargePlan> planList = smsWnsChargePlanMapper.selectList(new LambdaQueryWrapper<SmsWnsChargePlan>()
                .in(SmsWnsChargePlan::getId, planIdList)
                .orderByDesc(SmsWnsChargePlan::getCreateTime));

        planAndStatusListRespList = planList.stream().map(plan -> {
            PlanAndStatusListResp planAndStatusListResp = new PlanAndStatusListResp();
            BeanUtils.copyProperties(plan, planAndStatusListResp);

            // 过滤本计划缴费情况并收集
            List<SmsWnsChargePlanStudentStatus> filterStatusList = studentStatusList.stream().filter(status ->
                    status.getPlanId().equals(plan.getId())).collect(Collectors.toList());
            List<SmsWnsChargePlanStudentStatusResp> statusRespList = filterStatusList.stream().map(status -> {
                SmsWnsChargePlanStudentStatusResp statusResp = new SmsWnsChargePlanStudentStatusResp();
                BeanUtils.copyProperties(status, statusResp);

                // 设置大分类名
                SmsWnsChargeCategory chargeCategory = smsWnsChargeCategoryMapper.selectAllById(status.getCategoryId());
                if (chargeCategory != null) {
                    statusResp.setCategory(chargeCategory);
                }

                // 设置分类详情名
                SmsWnsChargeCategoryDetail detail = smsWnsChargeCategoryDetailMapper.selectAllById(status.getCategoryDetailId());
                if (detail != null) {
                    statusResp.setCategoryDetailName(detail.getName());
                }

                return statusResp;
            }).collect(Collectors.toList());

            planAndStatusListResp.setStatusRespList(statusRespList);

            return planAndStatusListResp;
        }).collect(Collectors.toList());

        return planAndStatusListRespList;
    }

    /**
     * 添加学生助学贷款可分配金额
     *
     * @param applyId 申请表Id
     * @return true/false
     */
    @Transactional
    public boolean addStudentLoanAmount(String applyId) {
        if (isNullOrEmpty(applyId)) {
            return false;
        }

        SmsWnsStudentLoanApply apply = smsWnsStudentLoanApplyMapper.selectById(applyId);
        if (apply == null) {
            return false;
        }

        String stuId = getStuIdByUserId(apply.getUserId());
        if (isNullOrEmpty(stuId)) {
            return false;
        }

        SmsWnsStudentLoanAmount studentLoanAmount = smsWnsStudentLoanAmountMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanAmount>()
                .eq(SmsWnsStudentLoanAmount::getUserId, apply.getUserId())
                .eq(SmsWnsStudentLoanAmount::getStuId, stuId));
        if (studentLoanAmount == null) {
            studentLoanAmount = new SmsWnsStudentLoanAmount();
            studentLoanAmount.setUserId(apply.getUserId());
            studentLoanAmount.setStuId(stuId);
            // 保存申请表id集合
            studentLoanAmount.setApplyIdList(JSON.toJSONString(Collections.singletonList(applyId)));
            // 设置贷款金额
            studentLoanAmount.setLoanAmount(apply.getLoanAmount());
            // 设置已使用金额
            studentLoanAmount.setUsedAmount(BigDecimal.ZERO);
            // 设置核销金额
            studentLoanAmount.setWriteOffAmount(BigDecimal.ZERO);

            smsWnsStudentLoanAmountMapper.insert(studentLoanAmount);
        } else {
            List<String> applyIdList = JSON.parseArray(studentLoanAmount.getApplyIdList(), String.class);
            applyIdList.add(applyId);
            studentLoanAmount.setApplyIdList(JSON.toJSONString(applyIdList));
            // 贷款余额 = 原余额 + 贷款金额
            studentLoanAmount.setLoanAmount(studentLoanAmount.getLoanAmount().add(apply.getLoanAmount()));

            smsWnsStudentLoanAmountMapper.updateById(studentLoanAmount);
        }

        // 添加学生助学贷款金额变动记录
        SmsWnsStudentLoanAmountRecord loanAmountRecord = new SmsWnsStudentLoanAmountRecord();
        loanAmountRecord.setLoanId(studentLoanAmount.getId());
        loanAmountRecord.setUserId(studentLoanAmount.getUserId());
        loanAmountRecord.setStuId(studentLoanAmount.getStuId());
        loanAmountRecord.setType(STUDENT_LOAN_AMOUNT_RECORD_TYPE_LOAN_AMOUNT);
        loanAmountRecord.setAmount(apply.getLoanAmount());
        loanAmountRecord.setNote(STUDENT_LOAN_AMOUNT_RECORD_DES_APPLY_PASS);
        smsWnsStudentLoanAmountRecordMapper.insert(loanAmountRecord);

        return true;
    }

}
